home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / gfx / misc / gnuplot-src.lha / gnuplot-3.7.1src / gnuplot-3.7.1.lha / gnuplot-3.7.1 / win / wtext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-21  |  50.0 KB  |  1,834 lines

  1. #ifndef lintîDiø&¨p,Sid = "$Id: wtext.c,v 1.3.2.1 1999/09/21 18:48:28 lhecking Exp $";
  2. #endif
  3.  
  4. /* GNUPLOT - win/wtext.c */
  5.  
  6. /*[
  7.  * Copyright 1992, 1993, 1998   Russell Lang
  8.  *
  9.  * Permission to use, copy, and distribute this software and its
  10.  * documentation for any purpose with or without fee is hereby granted,
  11.  * provided that the above copyright notice appear in all copies and
  12.  * that both that copyright notice and this permission notice appear
  13.  * in supporting documentation.
  14.  *
  15.  * Permission to modify the software is granted, but not the right to
  16.  * distribute the complete modified source code.  Modifications are to
  17.  * be distributed as patches to the released version.  Permission to
  18.  * distribute binaries produced by compiling modified sources is granted,
  19.  * provided you
  20.  *   1. distribute the corresponding source modifications from the
  21.  *    released version in the form of a patch file along with the binaries,
  22.  *   2. add special version identification to distinguish your version
  23.  *    in addition to the base release version number,
  24.  *   3. provide your name and address as the primary contact for the
  25.  *    support of your modified version, and
  26.  *   4. retain our contact information in regard to use of the base
  27.  *    software.
  28.  * Permission to distribute the released version of the source code along
  29.  * with corresponding source modifications in the form of a patch file is
  30.  * granted with same provisions 2 through 4 for binary distributions.
  31.  *
  32.  * This software is provided "as is" without express or implied warranty
  33.  * to the extent permitted by applicable law.
  34. ]*/
  35.  
  36. /*
  37.  * AUTHORS
  38.  * 
  39.  *   Russell Lang
  40.  * 
  41.  * Send your comments or suggestions to 
  42.  *  info-gnuplot@dartmouth.edu.
  43.  * This is a mailing list; to join it send a note to 
  44.  *  majordomo@dartmouth.edu.  
  45.  * Send bug reports to
  46.  *  bug-gnuplot@dartmouth.edu.
  47.  */
  48.  
  49. /* WARNING: Do not write to stdout/stderr with functions not listed 
  50.    in win/wtext.h */
  51.  
  52. #define STRICT
  53.  
  54. #include <string.h>    /* use only far items */
  55. #include <stdlib.h>
  56. #include <ctype.h>
  57. #include <dos.h>
  58. #ifndef __MSC__
  59. # include <mem.h>
  60. #endif
  61.  
  62. #include <windows.h>
  63. #include <windowsx.h>
  64. #if WINVER >= 0x030a
  65. # include <commdlg.h>
  66. #endif
  67.  
  68. #include "wgnuplib.h"
  69. #include "wresourc.h"
  70. #include "wcommon.h"
  71.  
  72. /* font stuff */
  73. #define TEXTFONTSIZE 9
  74. #define TEXTFONTNAME "Terminal"
  75.  
  76. #ifndef EOF /* HBB 980809: for MinGW32 */
  77. #define EOF -1        /* instead of using <stdio.h> */
  78. #endif
  79. /* limits */
  80. #define MAXSTR 256
  81. POINT ScreenMinSize = {16,4};
  82.  
  83. LRESULT CALLBACK WINEXPORT WndParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  84. LRESULT CALLBACK WINEXPORT WndTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  85.  
  86. void ReadTextIni(LPTW lptw);
  87. void LimitMark(LPTW lptw, POINT FAR *lppt);
  88.  
  89. char szNoMemory[] = "out of memory";
  90. COLORREF TextColorTable[16] = { 
  91.     RGB(0,0,0),            /* black */
  92.     RGB(0,0,128),        /* dark blue */
  93.     RGB(0,128,0),        /* dark green */
  94.     RGB(0,128,128),        /* dark cyan */
  95.     RGB(128,0,0),        /* dark red */
  96.     RGB(128,0,128),        /* dark magenta */
  97.     RGB(128,128,0),        /* dark yellow */
  98.     RGB(128,128,128),    /* dark grey */
  99.     RGB(192,192,192),    /* light grey */
  100.     RGB(0,0,255),        /* blue */
  101.     RGB(0,255,0),        /* green */
  102.     RGB(0,255,255),        /* cyan */
  103.     RGB(255,0,0),        /* red */
  104.     RGB(255,0,255),        /* magenta */
  105.     RGB(255,255,0),        /* yellow */
  106.     RGB(255,255,255),    /* white */
  107. };
  108. #define NOTEXT 0xF0
  109. #define MARKFORE RGB(255,255,255)
  110. #define MARKBACK RGB(0,0,128)
  111. #define TextFore(attr) TextColorTable[(attr) & 15]
  112. #define TextBack(attr) TextColorTable[(attr>>4) & 15]
  113.  
  114.  
  115. void WDPROC
  116. TextMessage(void)
  117. {
  118.     MSG msg;
  119.  
  120.     while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  121.         {
  122. #if 1 /* HBB 19990505: Petzold says we should check this: */
  123.         if (msg.message == WM_QUIT)
  124.             return;
  125. #endif
  126.         TranslateMessage(&msg);
  127.         DispatchMessage(&msg);
  128.         }
  129.     return;
  130. }
  131.  
  132.  
  133.  
  134. void
  135. CreateTextClass(LPTW lptw)
  136. {
  137. WNDCLASS wndclass;
  138. #ifdef WIN32
  139. hdllInstance = lptw->hInstance;    /* not using a DLL */
  140. #endif
  141.     wndclass.style = CS_HREDRAW | CS_VREDRAW;
  142.     wndclass.lpfnWndProc = WndTextProc;
  143.     wndclass.cbClsExtra = 0;
  144.     wndclass.cbWndExtra = 2 * sizeof(void FAR *);
  145.     wndclass.hInstance = lptw->hInstance;
  146.     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  147.     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  148.     wndclass.hbrBackground = NULL;
  149.     lptw->hbrBackground = CreateSolidBrush(lptw->bSysColors ? 
  150.         GetSysColor(COLOR_WINDOW) : RGB(0,0,0));
  151.     wndclass.lpszMenuName = NULL;
  152.     wndclass.lpszClassName = szTextClass;
  153.     RegisterClass(&wndclass);
  154.  
  155.     wndclass.style = CS_HREDRAW | CS_VREDRAW;
  156.     wndclass.lpfnWndProc = WndParentProc;
  157.     wndclass.cbClsExtra = 0;
  158.     wndclass.cbWndExtra = 2 * sizeof(void FAR *);
  159.     wndclass.hInstance = lptw->hInstance;
  160.     if (lptw->hIcon)
  161.         wndclass.hIcon = lptw->hIcon;
  162.     else
  163.         wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  164.     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  165.     wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  166.     wndclass.lpszMenuName = NULL;
  167.     wndclass.lpszClassName = szParentClass;
  168.     RegisterClass(&wndclass);
  169. }
  170.  
  171.  
  172. /* make text window */
  173. int WDPROC
  174. TextInit(LPTW lptw)
  175. {
  176.     RECT rect;
  177.     HMENU sysmenu;
  178.     HGLOBAL hglobal;
  179.     char buf[80];
  180.     
  181.     ReadTextIni(lptw);
  182.  
  183.     if (!lptw->hPrevInstance)
  184.         CreateTextClass(lptw);
  185.  
  186.     if (lptw->KeyBufSize == 0)
  187.         lptw->KeyBufSize = 256;
  188.  
  189.     if (lptw->ScreenSize.x < ScreenMinSize.x)
  190.         lptw->ScreenSize.x = ScreenMinSize.x;
  191.     if (lptw->ScreenSize.y < ScreenMinSize.y)
  192.         lptw->ScreenSize.y = ScreenMinSize.y;
  193.  
  194.     lptw->CursorPos.x = lptw->CursorPos.y = 0;
  195.     lptw->bFocus = FALSE;
  196.     lptw->bGetCh = FALSE;
  197.     lptw->CaretHeight = 0;
  198.     if (!lptw->nCmdShow)
  199.         lptw->nCmdShow = SW_SHOWNORMAL;
  200.     if (!lptw->Attr)
  201.         lptw->Attr = 0xf0;    /* black on white */
  202.  
  203.     hglobal = GlobalAlloc(GHND, lptw->ScreenSize.x * lptw->ScreenSize.y);
  204.     lptw->ScreenBuffer = (BYTE FAR *)GlobalLock(hglobal);
  205.     if (lptw->ScreenBuffer == (BYTE FAR *)NULL) {
  206.         MessageBox((HWND)NULL,szNoMemory,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  207.         return(1);
  208.     }
  209.     _fmemset(lptw->ScreenBuffer, ' ', lptw->ScreenSize.x * lptw->ScreenSize.y);
  210.     hglobal = GlobalAlloc(GHND, lptw->ScreenSize.x * lptw->ScreenSize.y);
  211.     lptw->AttrBuffer = (BYTE FAR *)GlobalLock(hglobal);
  212.     if (lptw->AttrBuffer == (BYTE FAR *)NULL) {
  213.         MessageBox((HWND)NULL,szNoMemory,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  214.         return(1);
  215.     }
  216.     _fmemset(lptw->AttrBuffer, NOTEXT, lptw->ScreenSize.x * lptw->ScreenSize.y);
  217.     hglobal = GlobalAlloc(LHND, lptw->KeyBufSize);
  218.     lptw->KeyBuf = (BYTE FAR *)GlobalLock(hglobal);
  219.     if (lptw->KeyBuf == (BYTE FAR *)NULL) {
  220.         MessageBox((HWND)NULL,szNoMemory,(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  221.         return(1);
  222.     }
  223.     lptw->KeyBufIn = lptw->KeyBufOut = lptw->KeyBuf;
  224.  
  225.     lptw->hWndParent = CreateWindow(szParentClass, lptw->Title,
  226.           WS_OVERLAPPEDWINDOW,
  227.           lptw->Origin.x, lptw->Origin.y,
  228.           lptw->Size.x, lptw->Size.y,
  229.           NULL, NULL, lptw->hInstance, lptw);
  230.     if (lptw->hWndParent == (HWND)NULL) {
  231.         MessageBox((HWND)NULL,"Couldn't open parent text window",(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  232.         return(1);
  233.     }
  234.     GetClientRect(lptw->hWndParent, &rect);
  235.  
  236.     lptw->hWndText = CreateWindow(szTextClass, lptw->Title,
  237.           WS_CHILD | WS_VSCROLL | WS_HSCROLL,
  238.           0, lptw->ButtonHeight,
  239.           rect.right, rect.bottom-lptw->ButtonHeight,
  240.           lptw->hWndParent, NULL, lptw->hInstance, lptw);
  241.     if (lptw->hWndText == (HWND)NULL) {
  242.         MessageBox((HWND)NULL,"Couldn't open text window",(LPSTR)NULL, MB_ICONHAND | MB_SYSTEMMODAL);
  243.         return(1);
  244.     }
  245.  
  246.     lptw->hPopMenu = CreatePopupMenu();
  247.     AppendMenu(lptw->hPopMenu, MF_STRING, M_COPY_CLIP, "&Copy to Clipboard");
  248.     AppendMenu(lptw->hPopMenu, MF_STRING, M_PASTE, "&Paste");
  249. #if WINVER >= 0x030a
  250.     AppendMenu(lptw->hPopMenu, MF_STRING, M_CHOOSE_FONT, "Choose &Font...");
  251. #endif
  252.     AppendMenu(lptw->hPopMenu, MF_STRING | (lptw->bSysColors ? MF_CHECKED : MF_UNCHECKED), 
  253.         M_SYSCOLORS, "&System Colors");
  254.     if (lptw->IniFile != (LPSTR)NULL) {
  255.         wsprintf(buf,"&Update %s",lptw->IniFile);
  256.         AppendMenu(lptw->hPopMenu, MF_STRING, M_WRITEINI, (LPSTR)buf);
  257.     }
  258.  
  259.     sysmenu = GetSystemMenu(lptw->hWndParent,0);    /* get the sysmenu */
  260.     AppendMenu(sysmenu, MF_SEPARATOR, 0, NULL);
  261.     AppendMenu(sysmenu, MF_POPUP, (UINT)lptw->hPopMenu, "&Options");
  262.     AppendMenu(sysmenu, MF_STRING, M_ABOUT, "&About");
  263.  
  264.     if (lptw->lpmw)
  265.         LoadMacros(lptw);
  266.  
  267.     ShowWindow(lptw->hWndText, SW_SHOWNORMAL);
  268.     BringWindowToTop(lptw->hWndText);
  269.     SetFocus(lptw->hWndText);
  270.     TextMessage();
  271.     return(0);
  272. }
  273.  
  274. /* close a text window */
  275. void WDPROC
  276. TextClose(LPTW lptw)
  277. {
  278.     HGLOBAL hglobal;
  279.  
  280.     /* close window */
  281.     if (lptw->hWndParent)
  282.         DestroyWindow(lptw->hWndParent);
  283.     TextMessage();
  284.  
  285.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lptw->ScreenBuffer) );
  286.     if (hglobal) {
  287.         GlobalUnlock(hglobal);
  288.         GlobalFree(hglobal);
  289.     }
  290.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lptw->AttrBuffer) );
  291.     if (hglobal) {
  292.         GlobalUnlock(hglobal);
  293.         GlobalFree(hglobal);
  294.     }
  295.     hglobal = (HGLOBAL)GlobalHandle( SELECTOROF(lptw->KeyBuf) );
  296.     if (hglobal) {
  297.         GlobalUnlock(hglobal);
  298.         GlobalFree(hglobal);
  299.     }
  300.  
  301.     if (lptw->lpmw)
  302.         CloseMacros(lptw);
  303.     lptw->hWndParent = (HWND)NULL;
  304. }
  305.     
  306. void
  307. WriteTextIni(LPTW lptw)
  308. {
  309.     RECT rect;
  310.     LPSTR file = lptw->IniFile;
  311.     LPSTR section = lptw->IniSection;
  312.     char profile[80];
  313.     int iconic;
  314.  
  315.     
  316.     if ((file == (LPSTR)NULL) || (section == (LPSTR)NULL))
  317.         return;
  318.     
  319.     iconic = IsIconic(lptw->hWndParent);
  320.     if (iconic)
  321.         ShowWindow(lptw->hWndParent, SW_SHOWNORMAL);
  322.     GetWindowRect(lptw->hWndParent,&rect);
  323.     wsprintf(profile, "%d %d", rect.left, rect.top);
  324.     WritePrivateProfileString(section, "TextOrigin", profile, file);
  325.     wsprintf(profile, "%d %d", rect.right-rect.left, rect.bottom-rect.top);
  326.     WritePrivateProfileString(section, "TextSize", profile, file);
  327.     wsprintf(profile, "%d", iconic);
  328.     WritePrivateProfileString(section, "TextMinimized", profile, file);
  329.     wsprintf(profile, "%s,%d", lptw->fontname, lptw->fontsize);
  330.     WritePrivateProfileString(section, "TextFont", profile, file);
  331.     wsprintf(profile, "%d", lptw->bSysColors);
  332.     WritePrivateProfileString(section, "SysColors", profile, file);
  333.     if (iconic)
  334.         ShowWindow(lptw->hWndParent, SW_SHOWMINIMIZED);
  335.     return;
  336. }
  337.  
  338. void
  339. ReadTextIni(LPTW lptw)
  340. {
  341.     LPSTR file = lptw->IniFile;
  342.     LPSTR section = lptw->IniSection;
  343.     char profile[81];
  344.     LPSTR p;
  345.     BOOL bOKINI;
  346.  
  347.     bOKINI = (file != (LPSTR)NULL) && (section != (LPSTR)NULL);
  348.     profile[0] = '\0';
  349.  
  350.     if (bOKINI)
  351.       GetPrivateProfileString(section, "TextOrigin", "", profile, 80, file);
  352.     if ( (p = GetInt(profile, (LPINT)&lptw->Origin.x)) == NULL)
  353.         lptw->Origin.x = CW_USEDEFAULT;
  354.     if ( (p = GetInt(p, (LPINT)&lptw->Origin.y)) == NULL)
  355.         lptw->Origin.y = CW_USEDEFAULT;
  356.     if ( (file != (LPSTR)NULL) && (section != (LPSTR)NULL) )
  357.       GetPrivateProfileString(section, "TextSize", "", profile, 80, file);
  358.     if ( (p = GetInt(profile, (LPINT)&lptw->Size.x)) == NULL)
  359.         lptw->Size.x = CW_USEDEFAULT;
  360.     if ( (p = GetInt(p, (LPINT)&lptw->Size.y)) == NULL)
  361.         lptw->Size.y = CW_USEDEFAULT;
  362.  
  363.     if (bOKINI)
  364.       GetPrivateProfileString(section, "TextFont", "", profile, 80, file);
  365.     {
  366.         char FAR *size;
  367.         size = _fstrchr(profile,',');
  368.         if (size) {
  369.             *size++ = '\0';
  370.             if ( (p = GetInt(size, &lptw->fontsize)) == NULL)
  371.                 lptw->fontsize = TEXTFONTSIZE;
  372.         }
  373.         _fstrcpy(lptw->fontname, profile);
  374.         if (lptw->fontsize == 0)
  375.             lptw->fontsize = TEXTFONTSIZE;
  376.         if (!(*lptw->fontname))
  377.             _fstrcpy(lptw->fontname,TEXTFONTNAME);
  378.     }
  379.  
  380.     if (bOKINI) {
  381.         int iconic;
  382.         GetPrivateProfileString(section, "TextMinimized", "", profile, 80, file);
  383.         if ((p = GetInt(profile, &iconic)) == NULL)
  384.             iconic = 0;
  385.         if (iconic)
  386.             lptw->nCmdShow = SW_SHOWMINIMIZED;
  387.     }
  388.     lptw->bSysColors = FALSE;
  389.     GetPrivateProfileString(section, "SysColors", "", profile, 80, file);
  390.     if ((p = GetInt(profile, &lptw->bSysColors)) == NULL)
  391.         lptw->bSysColors = 0;
  392. }
  393.  
  394.  
  395. /* Bring Cursor into text window */
  396. void WDPROC
  397. TextToCursor(LPTW lptw)
  398. {
  399. int nXinc=0;
  400. int nYinc=0;
  401. int cxCursor;
  402. int cyCursor;
  403.     cyCursor = lptw->CursorPos.y * lptw->CharSize.y;
  404.     if ( (cyCursor + lptw->CharSize.y > lptw->ScrollPos.y + lptw->ClientSize.y) 
  405.       || (cyCursor < lptw->ScrollPos.y) ) {
  406.         nYinc = max(0, cyCursor + lptw->CharSize.y - lptw->ClientSize.y) - lptw->ScrollPos.y;
  407.         nYinc = min(nYinc, lptw->ScrollMax.y - lptw->ScrollPos.y);
  408.     }
  409.     cxCursor = lptw->CursorPos.x * lptw->CharSize.x;
  410.     if ( (cxCursor + lptw->CharSize.x > lptw->ScrollPos.x + lptw->ClientSize.x)
  411.       || (cxCursor < lptw->ScrollPos.x) ) {
  412.         nXinc = max(0, cxCursor + lptw->CharSize.x - lptw->ClientSize.x/2) - lptw->ScrollPos.x;
  413.         nXinc = min(nXinc, lptw->ScrollMax.x - lptw->ScrollPos.x);
  414.     }
  415.     if (nYinc || nXinc) {
  416.         lptw->ScrollPos.y += nYinc;
  417.         lptw->ScrollPos.x += nXinc;
  418.         ScrollWindow(lptw->hWndText,-nXinc,-nYinc,NULL,NULL);
  419.         SetScrollPos(lptw->hWndText,SB_VERT,lptw->ScrollPos.y,TRUE);
  420.         SetScrollPos(lptw->hWndText,SB_HORZ,lptw->ScrollPos.x,TRUE);
  421.         UpdateWindow(lptw->hWndText);
  422.     }
  423. }
  424.  
  425. void
  426. NewLine(LPTW lptw)
  427. {
  428.     lptw->CursorPos.x = 0;
  429.     lptw->CursorPos.y++;
  430.     if (lptw->CursorPos.y >= lptw->ScreenSize.y) {
  431.         int i =  lptw->ScreenSize.x * (lptw->ScreenSize.y - 1);
  432.         _fmemmove(lptw->ScreenBuffer, lptw->ScreenBuffer+lptw->ScreenSize.x, i);
  433.         _fmemset(lptw->ScreenBuffer + i, ' ', lptw->ScreenSize.x);
  434.         _fmemmove(lptw->AttrBuffer, lptw->AttrBuffer+lptw->ScreenSize.x, i);
  435.         _fmemset(lptw->AttrBuffer + i, NOTEXT, lptw->ScreenSize.x);
  436.         lptw->CursorPos.y--;
  437.         ScrollWindow(lptw->hWndText,0,-lptw->CharSize.y,NULL,NULL);
  438.         lptw->MarkBegin.y--;
  439.         lptw->MarkEnd.y--;
  440.         LimitMark(lptw, &lptw->MarkBegin);
  441.         LimitMark(lptw, &lptw->MarkEnd);
  442.         UpdateWindow(lptw->hWndText);
  443.     }
  444.     if (lptw->CursorFlag)
  445.         TextToCursor(lptw);
  446.     TextMessage();
  447. }
  448.  
  449. /* Update count characters in window at cursor position */
  450. /* Updates cursor position */
  451. void
  452. UpdateText(LPTW lptw, int count)
  453. {
  454. HDC hdc;
  455. int xpos, ypos;
  456.     xpos = lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x;
  457.     ypos = lptw->CursorPos.y*lptw->CharSize.y - lptw->ScrollPos.y;
  458.     hdc = GetDC(lptw->hWndText);
  459.     if (lptw->bSysColors) {
  460.         SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  461.         SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  462.     }
  463.     else {
  464.         SetTextColor(hdc, TextFore(lptw->Attr));
  465.         SetBkColor(hdc, TextBack(lptw->Attr));
  466.     }
  467.     SelectObject(hdc, lptw->hfont);
  468.     TextOut(hdc,xpos,ypos,
  469.         (LPSTR)(lptw->ScreenBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + 
  470.         lptw->CursorPos.x), count);
  471.     (void)ReleaseDC(lptw->hWndText,hdc);
  472.     lptw->CursorPos.x += count;
  473.     if (lptw->CursorPos.x >= lptw->ScreenSize.x)
  474.         NewLine(lptw);
  475. }
  476.  
  477. int WDPROC
  478. TextPutCh(LPTW lptw, BYTE ch)
  479. {
  480. int pos;
  481.     switch(ch) {
  482.         case '\r':
  483.             lptw->CursorPos.x = 0;
  484.             if (lptw->CursorFlag)
  485.                 TextToCursor(lptw);
  486.             break;
  487.         case '\n':
  488.             NewLine(lptw);
  489.             break;
  490.         case 7:
  491.             MessageBeep(0xFFFFFFFF);
  492.             if (lptw->CursorFlag)
  493.                 TextToCursor(lptw);
  494.             break;
  495.         case '\t':
  496.             {
  497.             int n;
  498.                 for ( n = 8 - (lptw->CursorPos.x % 8); n>0; n-- )
  499.                     TextPutCh(lptw, ' ');
  500.             }
  501.             break;
  502.         case 0x08:
  503.         case 0x7f:
  504.             lptw->CursorPos.x--;
  505.             if (lptw->CursorPos.x < 0) {
  506.                 lptw->CursorPos.x = lptw->ScreenSize.x - 1;
  507.                 lptw->CursorPos.y--;
  508.             }
  509.             if (lptw->CursorPos.y < 0)
  510.                 lptw->CursorPos.y = 0;
  511.             break;
  512.         default:
  513.             pos = lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  514.             lptw->ScreenBuffer[pos] = ch;
  515.             lptw->AttrBuffer[pos] = lptw->Attr;
  516.             UpdateText(lptw, 1);
  517.     }
  518.     return ch;
  519. }
  520.  
  521. void 
  522. TextPutStr(LPTW lptw, LPSTR str)
  523. {
  524. BYTE FAR *p, FAR *pa;
  525. int count, limit;
  526.     while (*str) {
  527.         p = lptw->ScreenBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  528.         pa = lptw->AttrBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  529.         limit = lptw->ScreenSize.x - lptw->CursorPos.x;
  530.         for (count=0; (count < limit) && *str && (isprint(*str) || *str=='\t'); count++) {
  531.             if (*str=='\t') {
  532.                 int n;
  533.                 for ( n = 8 - ((lptw->CursorPos.x+count) % 8); (count < limit) & (n>0); n--, count++ ) {
  534.                     *p++ = ' ';
  535.                     *pa++ = lptw->Attr;
  536.                 }
  537.                 str++;
  538.                 count--;
  539.             }
  540.             else {
  541.                 *p++ = *str++;
  542.                 *pa++ = lptw->Attr;
  543.             }
  544.         }
  545.         if (count>0) {
  546.             UpdateText(lptw, count);
  547.         }
  548.         if (*str=='\n') {
  549.             NewLine(lptw);
  550.             str++;
  551.         }
  552.         else if (*str && !isprint(*str) && *str!='\t') {
  553.             TextPutCh(lptw, *str++);
  554.         }
  555.     }
  556. }
  557.  
  558.  
  559. void
  560. LimitMark(LPTW lptw, POINT FAR *lppt)
  561. {
  562.     if (lppt->x < 0)
  563.         lppt->x = 0;
  564.     if (lppt->y < 0) {
  565.         lppt->x = 0;
  566.         lppt->y = 0;
  567.     }
  568.     if (lppt->x > lptw->ScreenSize.x)
  569.         lppt->x = lptw->ScreenSize.x;
  570.     if (lppt->y >= lptw->ScreenSize.y) {
  571.         lppt->x = 0;
  572.         lppt->y = lptw->ScreenSize.y;
  573.     }
  574. }
  575.  
  576. void
  577. ClearMark(LPTW lptw, POINT pt)
  578. {
  579. RECT rect1, rect2, rect3;
  580. int tmp;
  581.   if ((lptw->MarkBegin.x != lptw->MarkEnd.x) || 
  582.       (lptw->MarkBegin.y != lptw->MarkEnd.y) ) {
  583.     if (lptw->MarkBegin.x > lptw->MarkEnd.x) {
  584.         tmp = lptw->MarkBegin.x;
  585.         lptw->MarkBegin.x = lptw->MarkEnd.x;
  586.         lptw->MarkEnd.x = tmp;
  587.     }
  588.     if (lptw->MarkBegin.y > lptw->MarkEnd.y) {
  589.         tmp = lptw->MarkBegin.y;
  590.         lptw->MarkBegin.y = lptw->MarkEnd.y;
  591.         lptw->MarkEnd.y = tmp;
  592.     }
  593.     /* calculate bounding rectangle in character coordinates */
  594.     if (lptw->MarkBegin.y != lptw->MarkEnd.y) {
  595.         rect1.left = 0;
  596.         rect1.right = lptw->ScreenSize.x;
  597.     }
  598.     else {
  599.         rect1.left = lptw->MarkBegin.x;
  600.         rect1.right = lptw->MarkEnd.x + 1;
  601.     }
  602.     rect1.top = lptw->MarkBegin.y;
  603.     rect1.bottom = lptw->MarkEnd.y + 1;
  604.     /* now convert to client coordinates */
  605.     rect1.left   = rect1.left   * lptw->CharSize.x - lptw->ScrollPos.x;
  606.     rect1.right  = rect1.right  * lptw->CharSize.x - lptw->ScrollPos.x;
  607.     rect1.top    = rect1.top    * lptw->CharSize.y - lptw->ScrollPos.y;
  608.     rect1.bottom = rect1.bottom * lptw->CharSize.y - lptw->ScrollPos.y;
  609.     /* get client rect and calculate intersection */
  610.     GetClientRect(lptw->hWndText, &rect2);
  611.     IntersectRect(&rect3,  &rect1, &rect2);
  612.     /* update window if necessary */
  613.     if (!IsRectEmpty(&rect3)) {
  614.         InvalidateRect(lptw->hWndText, &rect3, TRUE);
  615.     }
  616.   }
  617.   LimitMark(lptw, &pt);
  618.   lptw->MarkBegin.x = lptw->MarkEnd.x = pt.x;
  619.   lptw->MarkBegin.y = lptw->MarkEnd.y = pt.y;
  620.   UpdateWindow(lptw->hWndText);
  621. }
  622.  
  623.  
  624. /* output a line including attribute changes as needed */
  625. void
  626. DoLine(LPTW lptw, HDC hdc, int xpos, int ypos, int offset, int count)
  627. {
  628.     BYTE FAR *pa, attr;
  629.     int idx, num;
  630.     pa = lptw->AttrBuffer + offset;
  631. if ((offset < 0) || (offset >= lptw->ScreenSize.x*lptw->ScreenSize.y))
  632. MessageBox((HWND)NULL, "panic", "panic", MB_OK | MB_ICONEXCLAMATION);
  633.     idx = 0;
  634.     num = count;
  635.     while (num > 0) {
  636.         attr = *pa;
  637.         while ((num > 0) && (attr == *pa)) {
  638.             /* skip over bytes with same attribute */
  639.             num--;
  640.             pa++;
  641.         }
  642.         if (lptw->bSysColors) {
  643.             SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  644.             SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  645.         }
  646.         else {
  647.             SetTextColor(hdc, TextFore(attr));
  648.             SetBkColor(hdc, TextBack(attr));
  649.         }
  650.         TextOut(hdc,xpos,ypos, (LPSTR)(lptw->ScreenBuffer + offset + idx),
  651.             count-num-idx);
  652.         xpos += lptw->CharSize.x * (count-num-idx);
  653.         idx = count-num;
  654.     }
  655. }
  656.  
  657. void
  658. DoMark(LPTW lptw, POINT pt, POINT end, BOOL mark)
  659. {
  660. int xpos, ypos;
  661. HDC hdc;
  662. int count;
  663. int offset;
  664.     offset = lptw->ScreenSize.x * pt.y + pt.x;
  665.     hdc = GetDC(lptw->hWndText);
  666.     SelectObject(hdc, lptw->hfont);
  667.     if (lptw->bSysColors) {
  668.         SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  669.         SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
  670.     }
  671.     else {
  672.         SetTextColor(hdc, MARKFORE);
  673.         SetBkColor(hdc, MARKBACK);
  674.     }
  675.     while (pt.y < end.y) {
  676.         /* multiple lines */
  677.         xpos = pt.x*lptw->CharSize.x - lptw->ScrollPos.x;
  678.         ypos = pt.y*lptw->CharSize.y - lptw->ScrollPos.y;
  679.         count = lptw->ScreenSize.x - pt.x;
  680.         if (mark)
  681.             TextOut(hdc,xpos,ypos, (LPSTR)(lptw->ScreenBuffer + offset), count);
  682.         else {
  683.             DoLine(lptw, hdc, xpos, ypos, offset, count);
  684.             if (lptw->bSysColors) {
  685.                 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  686.                 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
  687.             }
  688.             else {
  689.                 SetTextColor(hdc, MARKFORE);
  690.                 SetBkColor(hdc, MARKBACK);
  691.             }
  692.         }
  693.         offset += count;
  694.         pt.y++;
  695.         pt.x=0;
  696.     }
  697.     /* partial line */
  698.     xpos = pt.x*lptw->CharSize.x - lptw->ScrollPos.x;
  699.     ypos = pt.y*lptw->CharSize.y - lptw->ScrollPos.y;
  700.     count = end.x - pt.x;
  701.     if (end.y != lptw->ScreenSize.y) {
  702.         if (mark)
  703.             TextOut(hdc,xpos,ypos, (LPSTR)(lptw->ScreenBuffer + offset), count);
  704.         else
  705.             DoLine(lptw, hdc, xpos, ypos, offset, count);
  706.     }
  707.     (void)ReleaseDC(lptw->hWndText,hdc);
  708. }
  709.  
  710. void
  711. UpdateMark(LPTW lptw, POINT pt)
  712. {
  713. int begin, point, end;
  714.     LimitMark(lptw, &pt);
  715.     begin = lptw->ScreenSize.x*lptw->MarkBegin.y + lptw->MarkBegin.x;
  716.     point = lptw->ScreenSize.x*pt.y + pt.x;
  717.     end   = lptw->ScreenSize.x*lptw->MarkEnd.y + lptw->MarkEnd.x;
  718.  
  719.     if (begin <= end) {
  720.         /* forward mark */
  721.         if (point >= end) {
  722.             /* extend marked area */
  723.             DoMark(lptw, lptw->MarkEnd, pt, TRUE);
  724.         }
  725.         else if (point >= begin) {
  726.             /* retract marked area */
  727.             DoMark(lptw, pt, lptw->MarkEnd, FALSE);
  728.         }
  729.         else {    /* retract and reverse */
  730.             DoMark(lptw, lptw->MarkBegin, lptw->MarkEnd, FALSE);
  731.             DoMark(lptw, pt, lptw->MarkBegin, TRUE);
  732.         }
  733.     }
  734.     else {
  735.         /* reverse mark */
  736.         if (point <= end) {
  737.             /* extend marked area */
  738.             DoMark(lptw, pt, lptw->MarkEnd, TRUE);
  739.         }
  740.         else if (point <= begin) {
  741.             /* retract marked area */
  742.             DoMark(lptw, lptw->MarkEnd, pt, FALSE);
  743.         }
  744.         else {    /* retract and reverse */
  745.             DoMark(lptw, lptw->MarkEnd, lptw->MarkBegin, FALSE);
  746.             DoMark(lptw, lptw->MarkBegin, pt, TRUE);
  747.         }
  748.     }
  749.     lptw->MarkEnd.x = pt.x;
  750.     lptw->MarkEnd.y = pt.y;
  751. }
  752.  
  753.  
  754. #if WINVER >= 0x030a
  755. /* Windows 3.1 drag-drop feature */
  756. char szFile[80];
  757. void
  758. DragFunc(LPTW lptw, HDROP hdrop)
  759. {
  760.     int i, cFiles;
  761.     LPSTR p;
  762.     if ( (lptw->DragPre==(LPSTR)NULL) || (lptw->DragPost==(LPSTR)NULL) )
  763.         return;
  764.     cFiles = DragQueryFile(hdrop, 0xffff, (LPSTR)NULL, 0);
  765.     for (i=0; i<cFiles; i++) {
  766.         DragQueryFile(hdrop, i, szFile, 80);
  767.         for (p=lptw->DragPre; *p; p++)
  768.             SendMessage(lptw->hWndText,WM_CHAR,*p,1L);
  769.         for (p=szFile; *p; p++)
  770.             SendMessage(lptw->hWndText,WM_CHAR,*p,1L);
  771.         for (p=lptw->DragPost; *p; p++)
  772.             SendMessage(lptw->hWndText,WM_CHAR,*p,1L);
  773.     }
  774.     DragFinish(hdrop);
  775. }
  776. #endif
  777.  
  778.  
  779. void
  780. TextCopyClip(LPTW lptw)
  781. {
  782.     int size, count;
  783.     HGLOBAL hGMem;
  784.     LPSTR cbuf, cp;
  785.     POINT pt, end;
  786.     TEXTMETRIC tm;
  787.     UINT type;
  788.     HDC hdc;
  789.  
  790.     if ((lptw->MarkBegin.x == lptw->MarkEnd.x) && 
  791.         (lptw->MarkBegin.y == lptw->MarkEnd.y) ) {
  792.         /* copy user text */
  793.         return;
  794.     }
  795.  
  796.     size = (lptw->MarkEnd.y - lptw->MarkBegin.y + 1) 
  797.         * (lptw->ScreenSize.x + 2) + 1;
  798.     hGMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)size);
  799.     cbuf = cp = (LPSTR)GlobalLock(hGMem);
  800.     if (cp == (LPSTR)NULL)
  801.         return;
  802.     
  803.     pt.x = lptw->MarkBegin.x;
  804.     pt.y = lptw->MarkBegin.y;
  805.     end.x   = lptw->MarkEnd.x;
  806.     end.y   = lptw->MarkEnd.y;
  807.  
  808.     while (pt.y < end.y) {
  809.         /* copy to global buffer */
  810.         count = lptw->ScreenSize.x - pt.x;
  811.         _fmemcpy(cp, lptw->ScreenBuffer + lptw->ScreenSize.x*pt.y+pt.x, count);
  812.         /* remove trailing spaces */
  813.         for (count=count-1; count>=0; count--) {
  814.             if (cp[count]!=' ')
  815.                 break;
  816.             cp[count] = '\0';
  817.         }
  818.         cp[++count] = '\r';
  819.         cp[++count] = '\n';
  820.         cp[++count] = '\0';
  821.         cp += count;
  822.         pt.y++;
  823.         pt.x=0;
  824.     }
  825.     /* partial line */
  826.     count = end.x - pt.x;
  827.     if (end.y != lptw->ScreenSize.y) {
  828.         _fmemcpy(cp, lptw->ScreenBuffer + lptw->ScreenSize.x*pt.y+pt.x, count);
  829.         cp[count] = '\0';
  830.     }
  831.     size = _fstrlen(cbuf) + 1;
  832.     GlobalUnlock(hGMem);
  833.     hGMem = GlobalReAlloc(hGMem, (DWORD)size, GMEM_MOVEABLE);
  834.     /* find out what type to put into clipboard */
  835.     hdc = GetDC(lptw->hWndText);
  836.     SelectObject(hdc, lptw->hfont);
  837.     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  838.     if (tm.tmCharSet == OEM_CHARSET)
  839.         type = CF_OEMTEXT;
  840.     else
  841.         type = CF_TEXT;
  842.     ReleaseDC(lptw->hWndText, hdc);
  843.     /* give buffer to clipboard */
  844.     OpenClipboard(lptw->hWndParent);
  845.     EmptyClipboard();
  846.     SetClipboardData(type, hGMem);
  847.     CloseClipboard();
  848. }
  849.  
  850. void
  851. TextMakeFont(LPTW lptw)
  852. {
  853.     LOGFONT lf;
  854.     TEXTMETRIC tm;
  855.     LPSTR p;
  856.     HDC hdc;
  857.  
  858.     hdc = GetDC(lptw->hWndText);
  859.     _fmemset(&lf, 0, sizeof(LOGFONT));
  860.     _fstrncpy(lf.lfFaceName,lptw->fontname,LF_FACESIZE);
  861.     lf.lfHeight = -MulDiv(lptw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  862.     lf.lfPitchAndFamily = FIXED_PITCH;
  863.     lf.lfCharSet = DEFAULT_CHARSET;
  864.     if ( (p = _fstrstr(lptw->fontname," Italic")) != (LPSTR)NULL ) {
  865.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  866.         lf.lfItalic = TRUE;
  867.     }
  868.     if ( (p = _fstrstr(lptw->fontname," Bold")) != (LPSTR)NULL ) {
  869.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  870.         lf.lfWeight = FW_BOLD;
  871.     }
  872.     if (lptw->hfont != 0)
  873.         DeleteObject(lptw->hfont);
  874.     lptw->hfont = CreateFontIndirect((LOGFONT FAR *)&lf);
  875.     /* get text size */
  876.     SelectObject(hdc, lptw->hfont);
  877.     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  878.     lptw->CharSize.y = tm.tmHeight;
  879.     lptw->CharSize.x = tm.tmAveCharWidth;
  880.     lptw->CharAscent = tm.tmAscent;
  881.     if (lptw->bFocus)
  882.         CreateCaret(lptw->hWndText, 0, lptw->CharSize.x, 2+lptw->CaretHeight);
  883.     ReleaseDC(lptw->hWndText, hdc);
  884.     return;
  885. }
  886.  
  887. void
  888. TextSelectFont(LPTW lptw) {
  889. #if WINVER >= 0x030a
  890.     LOGFONT lf;
  891.     CHOOSEFONT cf;
  892.     HDC hdc;
  893.     char lpszStyle[LF_FACESIZE]; 
  894.     LPSTR p;
  895.  
  896.     /* Set all structure fields to zero. */
  897.     _fmemset(&cf, 0, sizeof(CHOOSEFONT));
  898.     _fmemset(&lf, 0, sizeof(LOGFONT));
  899.     cf.lStructSize = sizeof(CHOOSEFONT);
  900.     cf.hwndOwner = lptw->hWndParent;
  901.     _fstrncpy(lf.lfFaceName,lptw->fontname,LF_FACESIZE);
  902.     if ( (p = _fstrstr(lptw->fontname," Bold")) != (LPSTR)NULL ) {
  903.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  904.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  905.     }
  906.     else if ( (p = _fstrstr(lptw->fontname," Italic")) != (LPSTR)NULL ) {
  907.         _fstrncpy(lpszStyle,p+1,LF_FACESIZE);
  908.         lf.lfFaceName[ (unsigned int)(p-lptw->fontname) ] = '\0';
  909.     }
  910.     else
  911.         _fstrcpy(lpszStyle,"Regular");
  912.     cf.lpszStyle = lpszStyle;
  913.     hdc = GetDC(lptw->hWndText);
  914.     lf.lfHeight = -MulDiv(lptw->fontsize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  915.     ReleaseDC(lptw->hWndText, hdc);
  916.     lf.lfPitchAndFamily = FIXED_PITCH;
  917.     cf.lpLogFont = &lf;
  918.     cf.nFontType = SCREEN_FONTTYPE;
  919.     cf.Flags = CF_SCREENFONTS | CF_FIXEDPITCHONLY | CF_INITTOLOGFONTSTRUCT | CF_USESTYLE;
  920.     if (ChooseFont(&cf)) {
  921.         RECT rect;
  922.         _fstrcpy(lptw->fontname,lf.lfFaceName);
  923.         lptw->fontsize = cf.iPointSize / 10;
  924.         if (cf.nFontType & BOLD_FONTTYPE)
  925.             lstrcat(lptw->fontname," Bold");
  926.         if (cf.nFontType & ITALIC_FONTTYPE)
  927.             lstrcat(lptw->fontname," Italic");
  928.         TextMakeFont(lptw);
  929.         /* force a window update */
  930.         GetClientRect(lptw->hWndText, (LPRECT) &rect);
  931.         SendMessage(lptw->hWndText, WM_SIZE, SIZE_RESTORED, 
  932.             MAKELPARAM(rect.right-rect.left, rect.bottom-rect.top));
  933.         GetClientRect(lptw->hWndText, (LPRECT) &rect);
  934.         InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  935.         UpdateWindow(lptw->hWndText);
  936.     }
  937. #endif
  938. }
  939.  
  940.  
  941. /* parent overlapped window */
  942. LRESULT CALLBACK WINEXPORT
  943. WndParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  944. {
  945.     HDC hdc;
  946.     PAINTSTRUCT ps;
  947.     RECT rect;
  948.     LPTW lptw;
  949.  
  950.     lptw = (LPTW)GetWindowLong(hwnd, 0);
  951.  
  952.     switch(message) {
  953.         case WM_SYSCOMMAND:
  954.             switch(LOWORD(wParam))
  955.             {
  956.                 case M_COPY_CLIP:
  957.                 case M_PASTE:
  958.                 case M_CHOOSE_FONT:
  959.                 case M_SYSCOLORS:
  960.                 case M_WRITEINI:
  961.                 case M_ABOUT:
  962.                   SendMessage(lptw->hWndText, WM_COMMAND, wParam, lParam);
  963.             }
  964.             break;
  965.         case WM_SETFOCUS: 
  966.             if (IsWindow(lptw->hWndText)) {
  967.                 SetFocus(lptw->hWndText);
  968.                 return(0);
  969.             }
  970.             break;
  971.         case WM_GETMINMAXINFO:
  972.             {
  973.                         POINT FAR * MMinfo = (POINT FAR *)lParam;
  974.             TEXTMETRIC tm;
  975.             hdc = GetDC(hwnd);
  976.             SelectObject(hdc, GetStockObject(OEM_FIXED_FONT));
  977.             GetTextMetrics(hdc,(LPTEXTMETRIC)&tm);
  978.             ReleaseDC(hwnd,hdc);
  979.             /* minimum size */
  980.             MMinfo[3].x = ScreenMinSize.x*tm.tmAveCharWidth
  981.                 + GetSystemMetrics(SM_CXVSCROLL) + 2*GetSystemMetrics(SM_CXFRAME);
  982.             MMinfo[3].y = ScreenMinSize.y*tm.tmHeight
  983.                 + GetSystemMetrics(SM_CYHSCROLL) + 2*GetSystemMetrics(SM_CYFRAME)
  984.                 + GetSystemMetrics(SM_CYCAPTION);
  985.             }
  986.             return(0);
  987.         case WM_SIZE:
  988.             SetWindowPos(lptw->hWndText, (HWND)NULL, 0, lptw->ButtonHeight,
  989.                 LOWORD(lParam), HIWORD(lParam)-lptw->ButtonHeight, 
  990.                 SWP_NOZORDER | SWP_NOACTIVATE);
  991.             return(0);
  992.         case WM_COMMAND:
  993.             if (IsWindow(lptw->hWndText))
  994.                 SetFocus(lptw->hWndText);
  995.             SendMessage(lptw->hWndText, message, wParam, lParam); /* pass on menu commands */
  996.             return(0);
  997.         case WM_PAINT:
  998.             {
  999.             hdc = BeginPaint(hwnd, &ps);
  1000.             if (lptw->ButtonHeight) {
  1001.                 HBRUSH hbrush;
  1002.                 GetClientRect(hwnd, &rect);
  1003.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
  1004.                 rect.bottom = lptw->ButtonHeight-1;
  1005.                 FillRect(hdc, &rect, hbrush);
  1006.                 DeleteObject(hbrush);
  1007.                 SelectObject(hdc, GetStockObject(BLACK_PEN));
  1008.                 MoveTo(hdc, rect.left, lptw->ButtonHeight-1);
  1009.                 LineTo(hdc, rect.right, lptw->ButtonHeight-1);
  1010.             }
  1011.             EndPaint(hwnd, &ps);
  1012.             return 0;
  1013.             }
  1014. #if WINVER >= 0x030a
  1015.         case WM_DROPFILES:
  1016.             {
  1017.             WORD version = LOWORD(GetVersion());
  1018.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1019.                 DragFunc(lptw, (HDROP)wParam);
  1020.             }
  1021.             break;
  1022. #endif
  1023.         case WM_CREATE:
  1024.             {
  1025.             RECT crect, wrect;
  1026.             TEXTMETRIC tm;
  1027.             lptw = ((CREATESTRUCT FAR *)lParam)->lpCreateParams;
  1028.             SetWindowLong(hwnd, 0, (LONG)lptw);
  1029.             lptw->hWndParent = hwnd;
  1030.             /* get character size */
  1031.             TextMakeFont(lptw);
  1032.             hdc = GetDC(hwnd);
  1033.             SelectObject(hdc, lptw->hfont);
  1034.             GetTextMetrics(hdc,(LPTEXTMETRIC)&tm);
  1035.             lptw->CharSize.y = tm.tmHeight;
  1036.             lptw->CharSize.x = tm.tmAveCharWidth;
  1037.             lptw->CharAscent = tm.tmAscent;
  1038.             ReleaseDC(hwnd,hdc);
  1039.             GetClientRect(hwnd, &crect);
  1040.             if ( lptw->CharSize.x*lptw->ScreenSize.x < crect.right ) {
  1041.                 /* shrink x size */
  1042.                 GetWindowRect(lptw->hWndParent,&wrect);
  1043.                 MoveWindow(lptw->hWndParent, wrect.left, wrect.top,
  1044.                  wrect.right-wrect.left + (lptw->CharSize.x*lptw->ScreenSize.x - crect.right),
  1045.                  wrect.bottom-wrect.top,
  1046.                  TRUE);
  1047.             }
  1048.             if ( lptw->CharSize.y*lptw->ScreenSize.y < crect.bottom ) {
  1049.                 /* shrink y size */
  1050.                 GetWindowRect(lptw->hWndParent,&wrect);
  1051.                 MoveWindow(lptw->hWndParent, wrect.left, wrect.top,
  1052.                  wrect.right-wrect.left,
  1053.                  wrect.bottom-wrect.top + (lptw->CharSize.y*lptw->ScreenSize.y+lptw->ButtonHeight - crect.bottom),
  1054.                  TRUE);
  1055.             }
  1056.             }
  1057. #if WINVER >= 0x030a
  1058.             {
  1059.             WORD version = LOWORD(GetVersion());
  1060.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1061.                 if ( (lptw->DragPre!=(LPSTR)NULL) && (lptw->DragPost!=(LPSTR)NULL) )
  1062.                     DragAcceptFiles(hwnd, TRUE);
  1063.             }
  1064. #endif
  1065.             break;
  1066.         case WM_DESTROY:
  1067. #if WINVER >= 0x030a
  1068.             {
  1069.             WORD version = LOWORD(GetVersion());
  1070.             if ((LOBYTE(version)*100 + HIBYTE(version)) >= 310)
  1071.                 DragAcceptFiles(hwnd, FALSE);
  1072.             }
  1073. #endif
  1074.             DeleteObject(lptw->hfont);
  1075.             lptw->hfont = 0;
  1076.             break;
  1077.         case WM_CLOSE:
  1078.             if (lptw->shutdown) {
  1079.                 FARPROC lpShutDown = lptw->shutdown;
  1080.                 (*lpShutDown)();
  1081.             }
  1082.             break;
  1083.     }
  1084.     return DefWindowProc(hwnd, message, wParam, lParam);
  1085. }
  1086.  
  1087. /* child text window */
  1088. LRESULT CALLBACK WINEXPORT
  1089. WndTextProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  1090. {
  1091.     HDC hdc;
  1092.     PAINTSTRUCT ps;
  1093.     RECT rect;
  1094.     int nYinc, nXinc;
  1095.     LPTW lptw;
  1096.  
  1097.     lptw = (LPTW)GetWindowLong(hwnd, 0);
  1098.  
  1099.     switch(message) {
  1100.         case WM_SETFOCUS: 
  1101.             lptw->bFocus = TRUE;
  1102.             CreateCaret(hwnd, 0, lptw->CharSize.x, 2+lptw->CaretHeight);
  1103.             SetCaretPos(lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x,
  1104.                 lptw->CursorPos.y*lptw->CharSize.y + lptw->CharAscent
  1105.                  - lptw->CaretHeight - lptw->ScrollPos.y);
  1106.             if (lptw->bGetCh)
  1107.                 ShowCaret(hwnd);
  1108.             break;
  1109.         case WM_KILLFOCUS: 
  1110.             DestroyCaret();
  1111.             lptw->bFocus = FALSE;
  1112.             break;
  1113.         case WM_SIZE:
  1114.             lptw->ClientSize.y = HIWORD(lParam);
  1115.             lptw->ClientSize.x = LOWORD(lParam);
  1116.  
  1117.             lptw->ScrollMax.y = max(0, lptw->CharSize.y*lptw->ScreenSize.y - lptw->ClientSize.y);
  1118.             lptw->ScrollPos.y = min(lptw->ScrollPos.y, lptw->ScrollMax.y);
  1119.  
  1120.             SetScrollRange(hwnd, SB_VERT, 0, lptw->ScrollMax.y, FALSE);
  1121.             SetScrollPos(hwnd, SB_VERT, lptw->ScrollPos.y, TRUE);
  1122.  
  1123.             lptw->ScrollMax.x = max(0, lptw->CharSize.x*lptw->ScreenSize.x - lptw->ClientSize.x);
  1124.             lptw->ScrollPos.x = min(lptw->ScrollPos.x, lptw->ScrollMax.x);
  1125.  
  1126.             SetScrollRange(hwnd, SB_HORZ, 0, lptw->ScrollMax.x, FALSE);
  1127.             SetScrollPos(hwnd, SB_HORZ, lptw->ScrollPos.x, TRUE);
  1128.  
  1129.             if (lptw->bFocus && lptw->bGetCh) {
  1130.                 SetCaretPos(lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x,
  1131.                     lptw->CursorPos.y*lptw->CharSize.y + lptw->CharAscent 
  1132.                     - lptw->CaretHeight - lptw->ScrollPos.y);
  1133.                 ShowCaret(hwnd);
  1134.             }
  1135.             return(0);
  1136.         case WM_VSCROLL:
  1137.             switch(LOWORD(wParam)) {
  1138.                 case SB_TOP:
  1139.                     nYinc = -lptw->ScrollPos.y;
  1140.                     break;
  1141.                 case SB_BOTTOM:
  1142.                     nYinc = lptw->ScrollMax.y - lptw->ScrollPos.y;
  1143.                     break;
  1144.                 case SB_LINEUP:
  1145.                     nYinc = -lptw->CharSize.y;
  1146.                     break;
  1147.                 case SB_LINEDOWN:
  1148.                     nYinc = lptw->CharSize.y;
  1149.                     break;
  1150.                 case SB_PAGEUP:
  1151.                     nYinc = min(-1,-lptw->ClientSize.y);
  1152.                     break;
  1153.                 case SB_PAGEDOWN:
  1154.                     nYinc = max(1,lptw->ClientSize.y);
  1155.                     break;
  1156.                 case SB_THUMBPOSITION:
  1157.                     nYinc = LOWORD(lParam) - lptw->ScrollPos.y;
  1158.                     break;
  1159.                 default:
  1160.                     nYinc = 0;
  1161.                 }
  1162.             if ( (nYinc = max(-lptw->ScrollPos.y, 
  1163.                 min(nYinc, lptw->ScrollMax.y - lptw->ScrollPos.y)))
  1164.                 != 0 ) {
  1165.                 lptw->ScrollPos.y += nYinc;
  1166.                 ScrollWindow(hwnd,0,-nYinc,NULL,NULL);
  1167.                 SetScrollPos(hwnd,SB_VERT,lptw->ScrollPos.y,TRUE);
  1168.                 Upda€åH            }
  1169.             return(0);
  1170.         case WM_HSCROLL:
  1171.             switch(LOWORD(wParam)) {
  1172.                 case SB_LINEUP:
  1173.                     nXinc = -lptw->CharSize.x;
  1174.                     break;
  1175.                 case SB_LINEDOWN:
  1176.                     nXinc = lptw->CharSize.x;
  1177.                     break;
  1178.                 case SB_PAGEUP:
  1179.                     nXinc = min(-1,-lptw->ClientSize.x);
  1180.                     break;
  1181.                 case SB_PAGEDOWN:
  1182.                     nXinc = max(1,lptw->ClientSize.x);
  1183.                     break;
  1184.                 case SB_THUMBPOSITION:
  1185.                     nXinc = LOWORD(lParam) - lptw->ScrollPos.x;
  1186.                     break;
  1187.                 default:
  1188.                     nXinc = 0;
  1189.                 }
  1190.             if ( (nXinc = max(-lptw->ScrollPos.x, 
  1191.                 min(nXinc, lptw->ScrollMax.x - lptw->ScrollPos.x)))
  1192.                 != 0 ) {
  1193.                 lptw->ScrollPos.x += nXinc;
  1194.                 ScrollWindow(hwnd,-nXinc,0,NULL,NULL);
  1195.                 SetScrollPos(hwnd,SB_HORZ,lptw->ScrollPos.x,TRUE);
  1196.                 UpdateWindow(hwnd);
  1197.             }
  1198.             return(0);
  1199.         case WM_KEYDOWN:
  1200.             if (GetKeyState(VK_SHIFT) < 0) {
  1201.               switch(wParam) {
  1202.                 case VK_HOME:
  1203.                     SendMessage(hwnd, WM_VSCROLL, SB_TOP, (LPARAM)0);
  1204.                     break;
  1205.                 case VK_END:
  1206.                     SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, (LPARAM)0);
  1207.                     break;
  1208.                 case VK_PRIOR:
  1209.                     SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, (LPARAM)0);
  1210.                     break;
  1211.                 case VK_NEXT:
  1212.                     SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, (LPARAM)0);
  1213.                     break;
  1214.                 case VK_UP:
  1215.                     SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, (LPARAM)0);
  1216.                     break;
  1217.                 case VK_DOWN:
  1218.                     SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, (LPARAM)0);
  1219.                     break;
  1220.                 case VK_LEFT:
  1221.                     SendMessage(hwnd, WM_HSCROLL, SB_LINEUP, (LPARAM)0);
  1222.                     break;
  1223.                 case VK_RIGHT:
  1224.                     SendMessage(hwnd, WM_HSCROLL, SB_LINEDOWN, (LPARAM)0);
  1225.                     break;
  1226.               }
  1227.             }
  1228.             else {
  1229.               switch(wParam) {
  1230.                 case VK_HOME:
  1231.                 case VK_END:
  1232.                 case VK_PRIOR:
  1233.                 case VK_NEXT:
  1234.                 case VK_UP:
  1235.                 case VK_DOWN:
  1236.                 case VK_LEFT:
  1237.                 case VK_RIGHT:
  1238.                 case VK_DELETE:
  1239.                 { /* store key in circular buffer */
  1240.                 long count;
  1241.                     count = lptw->KeyBufIn - lptw->KeyBufOut;
  1242.                     if (count < 0) count += lptw->KeyBufSize;
  1243.                     if (count < lptw->KeyBufSize-2) {
  1244.                         *lptw->KeyBufIn++ = 0;
  1245.                         if (lptw->KeyBufIn - lptw->KeyBuf >= lptw->KeyBufSize)
  1246.                             lptw->KeyBufIn = lptw->KeyBuf;    /* wrap around */
  1247.                         *lptw->KeyBufIn++ = HIWORD(lParam) & 0xff;
  1248.                         if (lptw->KeyBufIn - lptw->KeyBuf >= lptw->KeyBufSize)
  1249.                             lptw->KeyBufIn = lptw->KeyBuf;    /* wrap around */
  1250.                     }
  1251.                 }
  1252.               }
  1253.             }
  1254.             break;
  1255.         case WM_RBUTTONDOWN:
  1256.             {
  1257.             POINT pt;
  1258.             pt.x = LOWORD(lParam);
  1259.             pt.y = HIWORD(lParam);
  1260.             ClientToScreen(hwnd,&pt);
  1261.             TrackPopupMenu(lptw->hPopMenu, TPM_LEFTALIGN, 
  1262.                 pt.x, pt.y, 0, hwnd, NULL);
  1263.             }
  1264.             return(0);
  1265.         case WM_LBUTTONDOWN:
  1266.             { /* start marking text */
  1267.             POINT pt;
  1268.             pt.x = LOWORD(lParam);
  1269.             pt.y = HIWORD(lParam);
  1270.             pt.x = (pt.x + lptw->ScrollPos.x)/lptw->CharSize.x;
  1271.             pt.y = (pt.y + lptw->ScrollPos.y)/lptw->CharSize.y;
  1272.             ClearMark(lptw, pt);
  1273.             }
  1274.             SetCapture(hwnd);    /* track the mouse */
  1275.             lptw->Marking = TRUE;
  1276.             break;
  1277.         case WM_LBUTTONUP:
  1278.             { /* finish marking text */
  1279.             /* ensure begin mark is before end mark */
  1280.             ReleaseCapture();
  1281.             lptw->Marking = FALSE;
  1282.             if ((lptw->ScreenSize.x*lptw->MarkBegin.y + lptw->MarkBegin.x) >
  1283.                 (lptw->ScreenSize.x*lptw->MarkEnd.y   + lptw->MarkEnd.x)) {
  1284.                 POINT tmp;
  1285.                 tmp.x = lptw->MarkBegin.x;
  1286.                 tmp.y = lptw->MarkBegin.y;
  1287.                 lptw->MarkBegin.x = lptw->MarkEnd.x;
  1288.                 lptw->MarkBegin.y = lptw->MarkEnd.y;
  1289.                 lptw->MarkEnd.x   = tmp.x;
  1290.                 lptw->MarkEnd.y   = tmp.y;
  1291.             }
  1292.             }
  1293.             break;
  1294.         case WM_MOUSEMOVE:
  1295.             if ( (wParam & MK_LBUTTON) && lptw->Marking ) {
  1296.             RECT rect;
  1297.             POINT pt;
  1298.             pt.x = LOWORD(lParam);
  1299.             pt.y = HIWORD(lParam);
  1300.             GetClientRect(hwnd, &rect);
  1301.             if (PtInRect(&rect, pt)) {
  1302.                 pt.x = (pt.x + lptw->ScrollPos.x)/lptw->CharSize.x;
  1303.                 pt.y = (pt.y + lptw->ScrollPos.y)/lptw->CharSize.y;
  1304.                 UpdateMark(lptw, pt);
  1305.             }
  1306.             else {
  1307.               int nXinc;
  1308.               int nYinc;
  1309.               do {
  1310.                 nXinc = 0;
  1311.                 nYinc = 0;
  1312.                 if (pt.x > rect.right) {
  1313.                     nXinc = lptw->CharSize.x * 4;
  1314.                     pt.x = (rect.right + lptw->ScrollPos.x)/lptw->CharSize.x + 2;
  1315.                 }
  1316.                 else if (pt.x < rect.left) {
  1317.                     nXinc = -lptw->CharSize.x * 4;
  1318.                     pt.x = (rect.left + lptw->ScrollPos.x)/lptw->CharSize.x - 2;
  1319.                 }
  1320.                 else
  1321.                     pt.x = (pt.x + lptw->ScrollPos.x)/lptw->CharSize.x;
  1322.                 if (pt.y > rect.bottom) {
  1323.                     nYinc = lptw->CharSize.y;
  1324.                     pt.y = (rect.bottom + lptw->ScrollPos.y)/lptw->CharSize.y + 1;
  1325.                 }
  1326.                 else if (pt.y < rect.top) {
  1327.                     nYinc = -lptw->CharSize.y;
  1328.                     pt.y = (rect.top + lptw->ScrollPos.y)/lptw->CharSize.y - 1;
  1329.                 }
  1330.                 else
  1331.                     pt.y = (pt.y + lptw->ScrollPos.y)/lptw->CharSize.y;
  1332.                 LimitMark(lptw, &pt);
  1333.                 nXinc = max(nXinc, -lptw->ScrollPos.x);
  1334.                 nYinc = max(nYinc, -lptw->ScrollPos.y);
  1335.                 nYinc = min(nYinc, lptw->ScrollMax.y - lptw->ScrollPos.y);
  1336.                 nXinc = min(nXinc, lptw->ScrollMax.x - lptw->ScrollPos.x);
  1337.                 if (nYinc || nXinc) {
  1338.                     lptw->ScrollPos.y += nYinc;
  1339.                     lptw->ScrollPos.x += nXinc;
  1340.                     ScrollWindow(lptw->hWndText,-nXinc,-nYinc,NULL,NULL);
  1341.                     SetScrollPos(lptw->hWndText,SB_VERT,lptw->ScrollPos.y,TRUE);
  1342.                     SetScrollPos(lptw->hWndText,SB_HORZ,lptw->ScrollPos.x,TRUE);
  1343.                     UpdateWindow(lptw->hWndText);
  1344.                 }
  1345.                 UpdateMark(lptw, pt);
  1346.                 GetCursorPos(&pt);
  1347.                 ScreenToClient(hwnd, &pt);
  1348.               }
  1349.               while( (nYinc || nXinc) && !PtInRect(&rect, pt) &&
  1350.                 (GetAsyncKeyState(VK_LBUTTON) < 0) );
  1351.             }
  1352.             }
  1353.             break;
  1354.         case WM_CHAR:
  1355.             { /* store key in circular buffer */
  1356.             long count;
  1357.                 count = lptw->KeyBufIn - lptw->KeyBufOut;
  1358.                 if (count < 0) count += lptw->KeyBufSize;
  1359.                 if (count < lptw->KeyBufSize-1) {
  1360.                     *lptw->KeyBufIn++ = wParam;
  1361.                     if (lptw->KeyBufIn - lptw->KeyBuf >= lptw->KeyBufSize)
  1362.                         lptw->KeyBufIn = lptw->KeyBuf;    /* wrap around */
  1363.                 }
  1364.             }
  1365.             return(0);
  1366.         case WM_COMMAND:
  1367.             if (LOWORD(wParam) < NUMMENU)
  1368.                 SendMacro(lptw, LOWORD(wParam));
  1369.             else
  1370.             switch(LOWORD(wParam))
  1371.             {
  1372.                 case M_COPY_CLIP:
  1373.                     TextCopyClip(lptw);
  1374.                     return 0;
  1375.                 case M_PASTE:
  1376.                     {
  1377.                     HGLOBAL hGMem;
  1378.                     BYTE FAR *cbuf;
  1379.                     TEXTMETRIC tm;
  1380.                     UINT type;
  1381.                     /* find out what type to get from clipboard */
  1382.                     hdc = GetDC(hwnd);
  1383.                     SelectObject(hdc, lptw->hfont);
  1384.                     GetTextMetrics(hdc,(TEXTMETRIC FAR *)&tm);
  1385.                     if (tm.tmCharSet == OEM_CHARSET)
  1386.                         type = CF_OEMTEXT;
  1387.                     else
  1388.                         type = CF_TEXT;
  1389.                     ReleaseDC(lptw->hWndText, hdc);
  1390.                     /* now get it from clipboard */
  1391.                     OpenClipboard(hwnd);
  1392.                     hGMem = GetClipboardData(type);
  1393.                     if (hGMem) {
  1394.                         cbuf = (BYTE FAR *) GlobalLock(hGMem);
  1395.                         while (*cbuf) {
  1396.                             if (*cbuf != '\n')
  1397.                                 SendMessage(lptw->hWndText,WM_CHAR,*cbuf,1L);
  1398.                             cbuf++;
  1399.                         }
  1400.                         GlobalUnlock(hGMem);
  1401.                     }
  1402.                     CloseClipboard();
  1403.                     return 0;
  1404.                     }
  1405.                 case M_CHOOSE_FONT:
  1406.                     TextSelectFont(lptw);
  1407.                     return 0;
  1408.                 case M_SYSCOLORS:
  1409.                     lptw->bSysColors = !lptw->bSysColors;
  1410.                     if (lptw->bSysColors) 
  1411.                         CheckMenuItem(lptw->hPopMenu, M_SYSCOLORS, MF_BYCOMMAND | MF_CHECKED);
  1412.                     else
  1413.                         CheckMenuItem(lptw->hPopMenu, M_SYSCOLORS, MF_BYCOMMAND | MF_UNCHECKED);
  1414.                     SendMessage(hwnd, WM_SYSCOLORCHANGE, (WPARAM)0, (LPARAM)0);
  1415.                     InvalidateRect(hwnd, (LPRECT)NULL, 1);
  1416.                     UpdateWindow(hwnd);
  1417.                     return 0;
  1418.                 case M_WRITEINI:
  1419.                     WriteTextIni(lptw);
  1420.                     return 0;
  1421.                 case M_ABOUT:
  1422.                     AboutBox(hwnd,lptw->AboutText);
  1423.                     return 0;
  1424.             }
  1425.             return(0);
  1426.         case WM_SYSCOLORCHANGE:
  1427.             DeleteObject(lptw->hbrBackground);
  1428.             lptw->hbrBackground = CreateSolidBrush(lptw->bSysColors ? 
  1429.                 GetSysColor(COLOR_WINDOW) : RGB(0,0,0));
  1430.             return(0);
  1431.         case WM_ERASEBKGND:
  1432.             return(1);    /* we will erase it ourselves */
  1433.         case WM_PAINT:
  1434.             {
  1435.             POINT source, width, dest;
  1436.             POINT MarkBegin, MarkEnd;
  1437.             hdc = BeginPaint(hwnd, &ps);
  1438.             if (ps.fErase)
  1439.                 FillRect(hdc, &ps.rcPaint, lptw->hbrBackground);
  1440.             SelectObject(hdc, lptw->hfont);
  1441.             SetMapMode(hdc, MM_TEXT);
  1442.             SetBkMode(hdc,OPAQUE);
  1443.             GetClientRect(hwnd, &rect);
  1444.             source.x = (rect.left + lptw->ScrollPos.x) / lptw->CharSize.x;        /* source */
  1445.             source.y = (rect.top + lptw->ScrollPos.y) / lptw->CharSize.y;
  1446.             dest.x = source.x * lptw->CharSize.x - lptw->ScrollPos.x;                 /* destination */
  1447.             dest.y = source.y * lptw->CharSize.y - lptw->ScrollPos.y;
  1448.             width.x = ((rect.right  + lptw->ScrollPos.x + lptw->CharSize.x - 1) / lptw->CharSize.x) - source.x; /* width */
  1449.             width.y = ((rect.bottom + lptw->ScrollPos.y + lptw->CharSize.y - 1) / lptw->CharSize.y) - source.y;
  1450.             if (source.x < 0)
  1451.                 source.x = 0;
  1452.             if (source.y < 0)
  1453.                 source.y = 0;
  1454.             if (source.x+width.x > lptw->ScreenSize.x)
  1455.                 width.x = lptw->ScreenSize.x - source.x;
  1456.             if (source.y+width.y > lptw->ScreenSize.y)
  1457.                 width.y = lptw->ScreenSize.y - source.y;
  1458.             /* ensure begin mark is before end mark */
  1459.             if ((lptw->ScreenSize.x*lptw->MarkBegin.y + lptw->MarkBegin.x) >
  1460.                 (lptw->ScreenSize.x*lptw->MarkEnd.y   + lptw->MarkEnd.x)) {
  1461.                 MarkBegin.x = lptw->MarkEnd.x;
  1462.                 MarkBegin.y = lptw->MarkEnd.y;
  1463.                 MarkEnd.x   = lptw->MarkBegin.x;
  1464.                 MarkEnd.y   = lptw->MarkBegin.y;
  1465.             }
  1466.             else {
  1467.                 MarkBegin.x = lptw->MarkBegin.x;
  1468.                 MarkBegin.y = lptw->MarkBegin.y;
  1469.                 MarkEnd.x   = lptw->MarkEnd.x;
  1470.                 MarkEnd.y   = lptw->MarkEnd.y;
  1471.             }
  1472.             /* for each line */
  1473.             while (width.y>0) {
  1474.                 if ( (source.y >= MarkBegin.y) && (source.y <= MarkEnd.y) ) {
  1475.                     int start, end;
  1476.                     int count, offset;
  1477.                     if (source.y == MarkBegin.y)
  1478.                         start = MarkBegin.x;
  1479.                     else
  1480.                         start = 0;
  1481.                     if (source.y == MarkEnd.y)
  1482.                         end = MarkEnd.x;
  1483.                     else
  1484.                         end = lptw->ScreenSize.x;
  1485.                     /* do stuff before marked text */
  1486.                     offset = 0;
  1487.                     count = start - source.x;
  1488.                     if (count > 0)
  1489.                       DoLine(lptw, hdc, dest.x, dest.y, 
  1490.                         source.y*lptw->ScreenSize.x + source.x, count);
  1491.                     /* then the marked text */
  1492.                     offset += count;
  1493.                     count = end - start;
  1494.                     if ((count > 0) && (offset < width.x)){
  1495.                       if (lptw->bSysColors) {
  1496.                         SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
  1497.                         SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
  1498.                       }
  1499.                       else {
  1500.                         SetTextColor(hdc, MARKFORE);
  1501.                         SetBkColor(hdc, MARKBACK);
  1502.                       }
  1503.                       TextOut(hdc, dest.x + lptw->CharSize.x*offset, dest.y, 
  1504.                         (LPSTR)(lptw->ScreenBuffer + source.y*lptw->ScreenSize.x 
  1505.                         + source.x + offset), count);
  1506.                     }
  1507.                     /* then stuff after marked text */
  1508.                     offset += count;
  1509.                     count = width.x + source.x - end;
  1510.                     if ((count > 0) && (offset < width.x))
  1511.                       DoLine(lptw, hdc, dest.x + lptw->CharSize.x*offset, dest.y, 
  1512.                         source.y*lptw->ScreenSize.x + source.x + offset, count);
  1513.                 }
  1514.                 else {
  1515.                     DoLine(lptw, hdc, dest.x, dest.y, 
  1516.                         source.y*lptw->ScreenSize.x + source.x, width.x);
  1517.                 }
  1518.                 dest.y += lptw->CharSize.y;
  1519.                 source.y++;
  1520.                 width.y--;
  1521.             }
  1522.             EndPaint(hwnd, &ps);
  1523.             return 0;
  1524.             }
  1525.         case WM_CREATE:
  1526.             lptw = ((CREATESTRUCT FAR *)lParam)->lpCreateParams;
  1527.             SetWindowLong(hwnd, 0, (LONG)lptw);
  1528.             lptw->hWndText = hwnd;
  1529.             break;
  1530.         case WM_DESTROY:
  1531.             DeleteObject(lptw->hbrBackground);
  1532.             break;
  1533.     }
  1534.     return DefWindowProc(hwnd, message, wParam, lParam);
  1535. }
  1536.  
  1537.  
  1538. /* ================================== */
  1539. /* replacement stdio routines */
  1540.  
  1541. /* TRUE if key hit, FALSE if no key */
  1542. int WDPROC
  1543. TextKBHit(LPTW lptw)
  1544. {
  1545.     return (lptw->KeyBufIn != lptw->KeyBufOut);
  1546. }
  1547.  
  1548. /* get character from keyboard, no echo */
  1549. /* need to add extended codes */
  1550. int WDPROC
  1551. TextGetCh(LPTW lptw)
  1552. {
  1553.     int ch;
  1554.     TextToCursor(lptw);
  1555.     lptw->bGetCh = TRUE;
  1556.     if (lptw->bFocus) {
  1557.         SetCaretPos(lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x,
  1558.             lptw->CursorPos.y*lptw->CharSize.y + lptw->CharAscent 
  1559.             - lptw->CaretHeight - lptw->ScrollPos.y);
  1560.         ShowCaret(lptw->hWndText);
  1561.     }
  1562.         while (!TextKBHit(lptw)) { /* CMW: can't use TextMessage here as it does not idle properly */
  1563.                 MSG msg;
  1564.                 GetMessage(&msg, 0, 0, 0);
  1565.                 TranslateMessage(&msg);
  1566.                 DispatchMessage(&msg);
  1567.         }
  1568.     ch = *lptw->KeyBufOut++;
  1569.     if (ch=='\r')
  1570.         ch = '\n';
  1571.     if (lptw->KeyBufOut - lptw->KeyBuf >= lptw->KeyBufSize)
  1572.         lptw->KeyBufOut = lptw->KeyBuf;    /* wrap around */
  1573.     if (lptw->bFocus)
  1574.         HideCaret(lptw->hWndText);
  1575.     lptw->bGetCh = FALSE;
  1576.     return ch;
  1577. }
  1578.  
  1579. /* get character from keyboard, with echo */
  1580. int WDPROC
  1581. TextGetChE(LPTW lptw)
  1582. {
  1583. int ch;
  1584.     ch = TextGetCh(lptw);
  1585.     TextPutCh(lptw, (BYTE)ch);
  1586.     return ch;
  1587. }
  1588.  
  1589. LPSTR WDPROC
  1590. TextGetS(LPTW lptw, LPSTR str, unsigned int size)
  1591. {
  1592.     LPSTR next = str;
  1593.     while (--size>0) {
  1594.         switch(*next = TextGetChE(lptw)) {
  1595.             case EOF:
  1596.                 *next = 0;
  1597.                 if (next == str) return (char *)NULL;
  1598.                 return str;
  1599.             case '\n':
  1600.                 *(next+1) = 0;
  1601.                 return str;
  1602.             case 0x08:
  1603.             case 0x7f:
  1604.                 if (next > str)
  1605.                     --next;
  1606.                 break;
  1607.             default:
  1608.                 ++next;
  1609.         }
  1610.     }
  1611.     *next = 0;
  1612.     return str;
  1613. }
  1614.  
  1615. int WDPROC
  1616. TextPutS(LPTW lptw, LPSTR str)
  1617. {
  1618.     TextPutStr(lptw, str);
  1619.     return str[_fstrlen(str)-1];
  1620. }
  1621.  
  1622. /* ================================== */
  1623. /* routines added for elvis */
  1624.  
  1625. void WDPROC
  1626. TextGotoXY(LPTW lptw, int x, int y)
  1627. {
  1628.     lptw->CursorPos.x = x;
  1629.     lptw->CursorPos.y = y;
  1630. }
  1631.  
  1632. int  WDPROC
  1633. TextWhereX(LPTW lptw)
  1634. {
  1635.     return lptw->CursorPos.x;
  1636. }
  1637.  
  1638. int  WDPROC
  1639. TextWhereY(LPTW lptw)
  1640. {
  1641.     return lptw->CursorPos.y;
  1642. }
  1643.  
  1644. void WDPROC
  1645. TextCursorHeight(LPTW lptw, int height)
  1646. {
  1647.     lptw->CaretHeight = height;
  1648.     if (lptw->bFocus)
  1649.         CreateCaret(lptw->hWndText, 0, lptw->CharSize.x, 2+lptw->CaretHeight);
  1650. }
  1651.  
  1652. void WDPROC
  1653. TextClearEOL(LPTW lptw)
  1654. {
  1655. HDC hdc;
  1656. int xpos, ypos;
  1657. int from, len;
  1658. POINT pt;
  1659.     pt.x = pt.y = 0;
  1660.     ClearMark(lptw, pt);
  1661.     from = lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  1662.     len = lptw->ScreenSize.x-lptw->CursorPos.x;
  1663.     _fmemset(lptw->ScreenBuffer + from, ' ', len);
  1664.     _fmemset(lptw->AttrBuffer + from, NOTEXT, len);
  1665.     xpos = lptw->CursorPos.x*lptw->CharSize.x - lptw->ScrollPos.x;
  1666.     ypos = lptw->CursorPos.y*lptw->CharSize.y - lptw->ScrollPos.y;
  1667.     hdc = GetDC(lptw->hWndText);
  1668.     if (lptw->bSysColors) {
  1669.         SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  1670.         SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  1671.     }
  1672.     else {
  1673.         SetTextColor(hdc, TextFore(lptw->Attr));
  1674.         SetBkColor(hdc, TextBack(lptw->Attr));
  1675.     }
  1676.     SelectObject(hdc, (lptw->hfont));
  1677.     TextOut(hdc,xpos,ypos,
  1678.         (LPSTR)(lptw->ScreenBuffer + lptw->CursorPos.y*lptw->ScreenSize.x + 
  1679.         lptw->CursorPos.x), lptw->ScreenSize.x-lptw->CursorPos.x);
  1680.     (void)ReleaseDC(lptw->hWndText,hdc);
  1681. }
  1682.  
  1683. void WDPROC
  1684. TextClearEOS(LPTW lptw)
  1685. {
  1686. RECT rect;
  1687. int from, len;
  1688. POINT pt;
  1689.     pt.x = pt.y = 0;
  1690.     ClearMark(lptw, pt);
  1691.     from = lptw->CursorPos.y*lptw->ScreenSize.x + lptw->CursorPos.x;
  1692.     len = lptw->ScreenSize.x-lptw->CursorPos.x + 
  1693.             (lptw->ScreenSize.y-lptw->CursorPos.y-1)*lptw->ScreenSize.x;
  1694.     _fmemset(lptw->ScreenBuffer + from, ' ', len);
  1695.     _fmemset(lptw->AttrBuffer + from, NOTEXT, len);
  1696.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1697.     InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1698.     UpdateWindow(lptw->hWndText);
  1699. }
  1700.  
  1701. void WDPROC
  1702. TextInsertLine(LPTW lptw)
  1703. {
  1704. RECT rect;
  1705. int from, to, len;
  1706. POINT pt;
  1707.     pt.x = pt.y = 0;
  1708.     ClearMark(lptw, pt);
  1709.     from = lptw->CursorPos.y*lptw->ScreenSize.x,
  1710.     to = (lptw->CursorPos.y+1)*lptw->ScreenSize.x;
  1711.     len = (lptw->ScreenSize.y-lptw->CursorPos.y-1)*lptw->ScreenSize.x;
  1712.     _fmemmove(lptw->ScreenBuffer + to, lptw->ScreenBuffer + from, len);
  1713.     _fmemmove(lptw->AttrBuffer + to, lptw->AttrBuffer + from, len);
  1714.     _fmemset(lptw->ScreenBuffer + from, ' ', lptw->ScreenSize.x);
  1715.     _fmemset(lptw->AttrBuffer + from, NOTEXT, lptw->ScreenSize.x);
  1716.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1717.     InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1718.     UpdateWindow(lptw->hWndText);
  1719.     if (lptw->CursorFlag)
  1720.         TextToCursor(lptw);
  1721. }
  1722.  
  1723. void WDPROC
  1724. TextDeleteLine(LPTW lptw)
  1725. {
  1726. RECT rect;
  1727. int from, to, len;
  1728. POINT pt;
  1729.     pt.x = pt.y = 0;
  1730.     ClearMark(lptw, pt);
  1731.     to = lptw->CursorPos.y*lptw->ScreenSize.x,
  1732.     from = (lptw->CursorPos.y+1)*lptw->ScreenSize.x;
  1733.     len = (lptw->ScreenSize.y-lptw->CursorPos.y-1)*lptw->ScreenSize.x;
  1734.     _fmemmove(lptw->ScreenBuffer + to, lptw->ScreenBuffer + from, len);
  1735.     _fmemmove(lptw->AttrBuffer + to, lptw->AttrBuffer + from, len);
  1736.     from = lptw->ScreenSize.x*(lptw->ScreenSize.y -1);
  1737.     _fmemset(lptw->ScreenBuffer + from, ' ', lptw->ScreenSize.x);
  1738.     _fmemset(lptw->AttrBuffer + from, NOTEXT, lptw->ScreenSize.x);
  1739.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1740.     InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1741.     UpdateWindow(lptw->hWndText);
  1742.     if (lptw->CursorFlag)
  1743.         TextToCursor(lptw);
  1744. }
  1745.  
  1746. void WDPROC
  1747. TextScrollReverse(LPTW lptw)
  1748. {
  1749. RECT rect;
  1750. int len = lptw->ScreenSize.x * (lptw->ScreenSize.y - 1); 
  1751.     _fmemmove(lptw->ScreenBuffer+lptw->ScreenSize.x, lptw->ScreenBuffer, len);
  1752.     _fmemset(lptw->ScreenBuffer, ' ', lptw->ScreenSize.x);
  1753.     _fmemmove(lptw->AttrBuffer+lptw->ScreenSize.x, lptw->AttrBuffer, len);
  1754.     _fmemset(lptw->AttrBuffer, NOTEXT, lptw->ScreenSize.x);
  1755.     if (lptw->CursorPos.y)
  1756.         lptw->CursorPos.y--;
  1757.     ScrollWindow(lptw->hWndText,0,+lptw->CharSize.y,NULL,NULL);
  1758.     GetClientRect(lptw->hWndText, (LPRECT) &rect);
  1759.     rect.top = lptw->ScreenSize.y*lptw->CharSize.y;
  1760.     if (rect.top < rect.bottom)
  1761.         InvalidateRect(lptw->hWndText, (LPRECT) &rect, 1);
  1762.     lptw->MarkBegin.y++;
  1763.     lptw->MarkEnd.y++;
  1764.     LimitMark(lptw, &lptw->MarkBegin);
  1765.     LimitMark(lptw, &lptw->MarkEnd);
  1766.     UpdateWindow(lptw->hWndText);
  1767. }
  1768.  
  1769. void WDPROC 
  1770. TextAttr(LPTW lptw, BYTE attr)
  1771. {
  1772.     lptw->Attr = attr;
  1773. }
  1774.  
  1775. /* About Box */
  1776. BOOL CALLBACK WINEXPORT
  1777. AboutDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
  1778. {
  1779.     switch (wMsg) {
  1780.         case WM_INITDIALOG:
  1781.             {
  1782.             char buf[80];
  1783.             GetWindowText(GetParent(hDlg),buf,80);
  1784.             SetDlgItemText(hDlg, AB_TEXT1, buf);
  1785.             SetDlgItemText(hDlg, AB_TEXT2, (LPSTR)lParam);
  1786. #ifdef __DLL__
  1787.             wsprintf(buf,"WGNUPLOT.DLL Version %s",(LPSTR)WGNUPLOTVERSION);
  1788.             SetDlgItemText(hDlg, AB_TEXT3, buf);
  1789. #endif
  1790.             }
  1791.             return TRUE;
  1792.         case WM_DRAWITEM:
  1793.             {
  1794.             LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
  1795. #ifdef WIN32
  1796.             DrawIcon(lpdis->hDC, 0, 0, (HICON)GetClassLong(GetParent(hDlg), GCL_HICON));
  1797. #else
  1798.             DrawIcon(lpdis->hDC, 0, 0, (HICON)GetClassWord(GetParent(hDlg), GCW_HICON));
  1799. #endif
  1800.             }
  1801.             return FALSE;
  1802.         case WM_COMMAND:
  1803.             switch (LOWORD(wParam)) {
  1804.                 case IDCANCEL:
  1805.                 case IDOK:
  1806.                     EndDialog(hDlg, LOWORD(wParam));
  1807.                     return TRUE;
  1808.             }
  1809.             break;
  1810.     }
  1811.     return FALSE;
  1812. }
  1813.  
  1814.  
  1815. void WDPROC
  1816. AboutBox(HWND hwnd, LPSTR str)
  1817. {
  1818. #ifdef WIN32
  1819.     DialogBoxParam(hdllInstance,"AboutDlgBox",hwnd,AboutDlgProc,(LPARAM)str);
  1820. #else
  1821. DLGPROC lpfnAboutDlgProc;
  1822. #ifdef __DLL__
  1823.     lpfnAboutDlgProc = (DLGPROC)GetProcAddress(hdllInstance, "AboutDlgProc");
  1824. #else
  1825.     lpfnAboutDlgProc = (DLGPROC)MakeProcInstance((FARPROC)AboutDlgProc, hdllInstance);
  1826. #endif
  1827.     DialogBoxParam(hdllInstance,"AboutDlgBox",hwnd,lpfnAboutDlgProc,(LPARAM)str);
  1828.     EnableWindow(hwnd,TRUE);
  1829. #ifndef __DLL__
  1830.     FreeProcInstance((FARPROC)lpfnAboutDlgProc);
  1831. #endif
  1832. #endif
  1833. }
  1834.